/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http:  // www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "adaptortest.h"
#include <stdio.h>
#include <getopt.h>
#include <plugin.h>
#include <memory>
#include <string>
#include <vector>
#include<iostream>
#include "hilog_wrapper.h"
#include "plugin_manager.h"

using namespace SwanLink::Finance;


static PluginManager *g_pPlugMgr;

const char* g_func[] = {
    "int Open(const Transport &tran)",
    "int Close()",
    "bool IsOpen()",
    "int Reset()",
    "int GetStatus(int module, char *err)"
};

void showhelp();
std::vector<std::string> get_args_from_stdin(int num);

int main(int argc, char *argv[])
{
    if (argc <= 2) {
        printf("parameter not enough");
        return 0;
    }
    int opt;
    ACCESS_MODE mode;
    std::string name;
    std::string dev;
    std::string attr;

    while ((opt = getopt(argc, argv, "t:m:n:d:h")) != -1) {
        switch (opt) {
        case 't':
            attr = optarg;
            printf("attr = %s ", attr.c_str());
            break;
        case 'm':
            mode = (ACCESS_MODE)atoi(optarg);
            printf("mode: %d ", (int)mode);
            break;
        case 'n':
            name = optarg;
            printf("name = %s ", name.c_str());
            break;
        case 'd':
            dev = optarg;
            printf("dev = %s ", dev.c_str());
            break;
        case 'h':
        default:
            showhelp();
            return 0;
        }
    }
    printf("\n");

    g_pPlugMgr = new PluginManager();
    if (!g_pPlugMgr->LoadAllPlugin(attr)) {
        printf("load plugin failed");
        return 0;
    }

    DevAccess access;
    if ( !g_pPlugMgr->GetAccess(name, mode, dev, access) ) {
        printf("get access failed\n");
        return 0;
    }
    printf("get access :mode = %d, name = %s, desc = %s\n",
        access.transport.mode, access.name, access.desc);

    std::shared_ptr<IAdaptor> adaptor  = g_pPlugMgr->CreateAdaptor(name);
    if (adaptor == nullptr) {
        printf("create Adaptor failed\n");
        return 0;
    }

    showhelp();

    std::vector<std::string> args_list;
    int ch;
    printf("please input function index:\n");
    std::cin >> ch;
    while (ch >= 0) {
        if (ch >= sizeof(g_func)/sizeof(g_func[0])) {
            break;
        }
        printf("func: %s\n", g_func[ch]);

        switch (ch) {
        case 0:
            printf("result = %d\n", adaptor->Open(access.transport));
            break;
        case 1:
            adaptor->Close();
            break;
        case 2:
            printf("result = %d\n", adaptor->IsOpen());
            break;
        case 3:
            adaptor->Reset();
            break;
        case 4: {
            char err[256];
            int status;
            args_list = get_args_from_stdin(1);
            status = adaptor->GetStatus(atoi(args_list[0].c_str()), err);
            printf("status = %d\n", status);
            break;
        }
        default:
            break;
        }
        showhelp();
        printf("please input function index:\n");
        std::cin >> ch;
    }
    printf("exit !\n");
    delete g_pPlugMgr;
    return 0;
}

void showhelp() {
    printf("funcs list:\n");
    for (size_t i = 0; i < sizeof(g_func)/sizeof(g_func[0]); i++) {
        printf("\tcase %d: %s\n", static_cast<int>(i), g_func[i]);
    }
    printf("\n");
}

std::vector<std::string> get_args_from_stdin(int num) {
    std::vector<std::string> args_list;
    for (int i = 0; i < num; i++) {
        std::string attr;
        printf("param [%d]:\n", i+1);
        std::cin >> attr;
        args_list.push_back(attr);
    }
    return args_list;
}